/**
 * Created by renjie on 2015/7/3.
 */

(function (window) {
  // 状态描述
  var GameState = {
    STATE_INIT: 0,
    STATE_STEP: 1,
    STATE_RUN: 2,
    STATE_OVER: 3,
  };

  // *) 游戏场景的构造
  class GameScene {
    constructor() {
      this.tetrisUnit = new TetrisUnit();
      this.strategy = new AIStrategy();
      this.moves = [];

      this.gameState = GameState.STATE_INIT;

      this.currentShape = null;
      this.nextShape = null;

      this.timestamp = new Date().getTime();

      this.score = 0;
      this.curRandomNum = 12358;
      this.brickCount = 0;
      this.randomConfig = {
        a: 27073, // 乘子
        M: 32749, // 模数
        C: 17713, // 增量
        v: 12358, // 随机数种子
      };
    }
    createShape(randomNum, brickCount) {
      // 获取当前方块信息
      // const defaultBrickCenterPos = [4, 0];
      // const curBrickCenterPos = defaultBrickCenterPos.slice();
      // const { isValid, brickRawInfo, brickInfo } = this.getBrickInfo(
      //   this.curRandomNum, // 当前随机数
      //   this.brickCount, // 当前方块个数
      //   curBrickCenterPos
      // );

      // console.log(brickRawInfo, brickInfo);
      const weightIndex = randomNum % 29; // 对形状的概率有一定要求：限制每种砖块的出现概率可以让游戏变得更有挑战性
      const stateIndex = brickCount % 4; // 形态概率要求不高，随机即可
      const colorIndex = brickCount % 4; // 颜色概率要求不高，随机即可
      let shapeIndex = 0;
      // I,L,J,T,O,S,Z 型方块的概率权重分别为：2,3,3,4,5,6,6（和为29）
      if (weightIndex >= 0 && weightIndex <= 1) {
        shapeIndex = 0;
      } else if (weightIndex > 1 && weightIndex <= 4) {
        shapeIndex = 1;
      } else if (weightIndex > 4 && weightIndex <= 7) {
        shapeIndex = 2;
      } else if (weightIndex > 7 && weightIndex <= 11) {
        shapeIndex = 3;
      } else if (weightIndex > 11 && weightIndex <= 16) {
        shapeIndex = 4;
      } else if (weightIndex > 16 && weightIndex <= 22) {
        shapeIndex = 5;
      } else if (weightIndex > 22) {
        shapeIndex = 6;
      }

      var shapeTypes = [IShape, LShape, JShape, TShape, OShape, SShape, ZShape];
      var colorTypes = ["red", "green", "blue", "pink"];

      // var shapeIdx = Math.floor(Math.random() * 100) % shapeTypes.length;
      // var shapePos = Math.floor(Math.random() * 100) % 4;
      // var colorIdx = Math.floor(Math.random() * 100) % colorTypes.length;

      return new shapeTypes[shapeIndex](
        4,
        -1,
        stateIndex,
        colorTypes[colorIndex]
      );
    }
    getRandomNum(v) {
      // 随机数生成函数的配置
      const { a, C, M } = this.randomConfig; // a：乘子，C：模数、C：增量
      return (v * a + C) % M;
    }

    // others!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    initGame() {
      this.tetrisUnit.reset();
    }
    startGame() {
      this.gameState = GameState.STATE_STEP;
      this.curRandomNum = this.getRandomNum(this.curRandomNum);
      this.currentShape = this.createShape(this.curRandomNum, this.brickCount);
      this.brickCount += 1;
      this.curRandomNum = this.getRandomNum(this.curRandomNum);
      this.nextShape = this.createShape(this.curRandomNum, this.brickCount);
      this.brickCount += 1;

      this.score = 0;

      this.tetrisUnit.reset();
      this.timestamp = new Date().getTime();

      var moveAns = this.strategy.makeBestDecision(
        this.tetrisUnit,
        this.currentShape
      );
      this.moves = moveAns.action_moves;
      this.action_str += moveAns.action_str;
    }
    updateScore(line) {
      switch (line) {
        case 1:
          this.score += 100;
          break;
        case 2:
          this.score += 300;
          break;
        case 3:
          this.score += 500;
          break;
        case 4:
          this.score += 800;
          break;
        default:
      }
    }
    updateGame() {
      // *) 状态判断
      if (this.gameState === GameState.STATE_INIT) {
        return;
      }

      var now = new Date().getTime();
      if (now - this.timestamp > 5) {
        if (this.currentShape != null) {
          if (this.moves.length > 0) {
            this.currentShape.x = this.moves[0].x;
            this.currentShape.y = this.moves[0].y;
            this.currentShape.idx = this.moves[0].idx;
            this.moves.splice(0, 1);
          } else if (this.detect(ActionType.ACTION_DOWN)) {
            this.currentShape.doAction(ActionType.ACTION_DOWN);
          } else {
            var tx = this.currentShape.x;
            var ty = this.currentShape.y;
            var shapeArr = this.currentShape.shapes[this.currentShape.idx];

            var eliminatedLines = this.tetrisUnit.touchDown(tx, ty, shapeArr);
            this.updateScore(eliminatedLines);

            // ********************************** 创建新的block ************************************************
            this.currentShape = this.nextShape;
            this.curRandomNum = this.getRandomNum(this.curRandomNum);
            this.nextShape = this.createShape(
              this.curRandomNum,
              this.brickCount
            );
            this.brickCount += 1;

            // *) 判断游戏是否结束
            if (this.detectGameOver()) {
              alert("Game Over\n you had " + this.score + " points");
              this.initGame();
            } else {
              // *)
              var moveAns = this.strategy.makeBestDecision(
                this.tetrisUnit,
                this.currentShape
              );
              this.moves = moveAns.action_moves;
              this.action_str += moveAns.action_str;
            }
          }
        }
        this.timestamp = now;
      } else {
        if (this.moves.length > 0) {
          if (
            this.moves[0].x === this.currentShape.x &&
            this.moves[0].y === this.currentShape.y + 1 &&
            this.moves[0].idx === this.currentShape.idx
          ) {
            this.currentShape.y = this.moves[0].y;
            this.moves.splice(0, 1);
          }
        }
      }
    }
    renderGame(ctx) {
      ctx.fillStyle = "white";
      ctx.fillRect(0, 0, 800, 640);

      ctx.strokeStyle = "rgb(125, 0, 0)";
      ctx.strokeRect(0, 0, 20 * this.col, 20 * this.row);

      if (this.gameState === GameScene.STATE_INIT) {
        return;
      }

      this.tetrisUnit.render(ctx);

      if (this.currentShape != null) {
        this.currentShape.render(ctx);
      }

      // *) 绘制傍边的信息条
      this.drawInfo(ctx);
    }
    drawInfo(ctx) {
      if (this.gameState === GameState.STATE_INIT) {
        return;
      }

      ctx.strokeStyle = "rgba(0, 0, 180, 127)";
      ctx.strokeRect(210, 0, 100, 200);

      ctx.font = "16px Courier New";
      //设置字体填充颜色
      ctx.fillStyle = "blue";
      //从坐标点(50,50)开始绘制文字
      if (this.nextShape !== null) {
        ctx.fillText("Next:", 220, 18);
        this.nextShape.display(ctx, 220, 36);
      }

      ctx.fillText("Score: ", 220, 138);
      ctx.fillText("  " + this.score, 220, 156);
    }
    // 测试是否可以
    detect(cmd) {
      var tidx = this.currentShape.idx;
      var tx = this.currentShape.x;
      var ty = this.currentShape.y;

      switch (cmd) {
        case ActionType.ACTION_LEFT:
          tx = this.currentShape.x - 1;
          break;
        case ActionType.ACTION_RIGHT:
          tx = this.currentShape.x + 1;
          break;
        case ActionType.ACTION_CHANGE:
          tidx = (this.currentShape.idx + 1) % 4;
          break;
        case ActionType.ACTION_DOWN:
          ty = this.currentShape.y + 1;
          break;
      }
      var shapeArr = this.currentShape.shapes[tidx];

      return this.tetrisUnit.checkAvailable(tx, ty, shapeArr);
    }
    detectGameOver() {
      var shapeArr = this.currentShape.shapes[this.currentShape.idx];
      return this.tetrisUnit.isOverlay(
        this.currentShape.x,
        this.currentShape.y,
        shapeArr
      );
    }
  }

  var canvas = document.getElementById("canvas");
  var ctx = canvas.getContext("2d");

  var gameScene = new GameScene();
  gameScene.initGame();
  gameScene.startGame();

  var fps = 5 || 0;
  setInterval(gameLogic, fps);

  function gameLogic() {
    gameScene.updateGame();
    gameScene.renderGame(ctx);
  }
})(window);
